package com.godenwater.recv.manager;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.godenwater.core.spring.Application;
import com.godenwater.recv.server.hd.HdDownCommand;
import com.godenwater.recv.spring.Configurer;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.mina.core.future.WriteFuture;
import org.apache.mina.core.session.IoSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.gov.mwr.sl651.utils.ByteUtil;
import cn.gov.mwr.sl651.utils.CRC16Helper;

import com.godenwater.core.container.BasicModule;
import com.godenwater.recv.server.all.RtuConfig;
import com.godenwater.recv.server.all.RtuServer;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;

/**
 * session管理器,在这里可以对session进行管理,如会话时间超长的管理
 *
 * @author goldenwater
 */
public class SessionManager extends BasicModule {

    private static Logger logger = LoggerFactory.getLogger(SessionManager.class);

    private static SimpleDateFormat sdf = new SimpleDateFormat("yyMMddHHmmss");

    // 定义当前在线的连接池，为了群发使用
    private final Set<IoSession> inSessions = Collections.synchronizedSet(new HashSet<IoSession>());

    private final Map<String, List> stcdSessions = new HashMap<String, List>();

    // Wrap this guy up so we can mock out the UserManager class.
    private static class SessionManagerContainer {
        private static SessionManager instance = new SessionManager();
    }

    RedisManager redisManager = new RedisManager();

    /**
     * Returns a singleton UserManager instance.
     *
     * @return a UserManager instance.
     */
    public static SessionManager getInstance() {
        return SessionManagerContainer.instance;
    }

    public SessionManager() {
        super("Session Manager");
    }

    public int getSessionsCount() {
        return inSessions.size();
    }

    public void createSession(IoSession session) {
        inSessions.add(session);
    }

    private String online = Configurer.getStringProperty("hydro.station.online", "10");
    private String onlineNoData = Configurer.getStringProperty("hydro.station.online.noData", "5");

    /**
     * 当由客户端主动关闭连接时，会触发此操作。
     *
     * @param session
     */
    public void removeSession(IoSession session) {
        try {
            inSessions.remove(session);
            if (!session.isClosing()) {
                session.close(false);
            }
        } catch (Exception ex) {
            logger.error("session colse error:" + ex);
            ex.printStackTrace();

        }
    }

    public Set<IoSession> getIoSession() {
        return inSessions;
    }

    /**
     * 测站 -》 移动运营商 -》 中心 其实，中心连接是移动运营商，所以这个会话时间其实是由移动运营商来控制的。
     *
     * @param session
     */
    public void idleSession(IoSession session) {

        // 用当前的时间减去空闲的时间,
        // 空闲时间超过限制，则需要关闭此session
        // logger.info(">> clients size " + clients.size());
        String stcd = (String) session.getAttribute("STCD");
//        logger.info("测站在线个数为：" + getSessionsCount());
        long starttime = session.getCreationTime();
        long endtime = new Date().getTime();
        //long endtime=session.getLastIoTime();
        long delay = endtime - starttime;

        if (delay > (Double.parseDouble(online) * 60 * 1000)) {
            // 此处的时间，可以根据服务器的设置进行调整。（可以改成配置参数来控制）
            //logger.info( ">> 服务端主动清除 的session " + stcd+",测站在线时长为 " + delay / 1000 + " 秒。" );
            //System.out.println(">> 服务端主动清除" + stcd + " 的session " + ",测站在线时长为 " + delay / 1000 + " 秒。");
            // 将在线的Session从对应的stcd队列中删除
            removeSession(session);
            // 关闭session，不进行主动关闭session操作，厂商会发送心跳包过来（可以改成配置参数来控制）

            //logger.info("清除会话连接:" + stcd);

            //如果是亿力能的 设备让他在线一分钟就下线
        }

        try {
            //String stcd = (String) session.getAttribute( "STCD" );
            String protocol = (String) session.getAttribute("PROTOCOL");
            String telphone = (String) session.getAttribute("TELPHONE");
            String caller = (String) session.getAttribute("CALLER");//召测标识，如果为true表示需要进行召测
            String upFlag = (String) session.getAttribute("UPGRADE");//升级标识

            //属于宏电的协议，需根据宏电的向上发送报文
            if (StringUtils.equalsIgnoreCase(protocol, "YY")) {
                String hdFlag = (String) session.getAttribute("HD");//是否有宏电模块
                hdFlag = StringUtils.isNotBlank(hdFlag) ? hdFlag : "0";
                String center = (String) session.getAttribute("CENTER");//中心站地址
                center = StringUtils.isNotBlank(center) ? center : "fe";
                String borrow = (String) session.getAttribute("BORROW");//借位地址
                borrow = StringUtils.isNotBlank(borrow) ? borrow : "";
                //System.out.println(">>> 宏电报文下发检测完成");
                try {

                    // 燕禹测站，把电话号码添加到redis 内存

                    if (StringUtils.isNotBlank(stcd) && StringUtils.isNotBlank(telphone)) {
                        RedisManager redisManager = new RedisManager();
                        redisManager.setYyTel(stcd + "$" + telphone + "$" + hdFlag + "$" + center + "$" + borrow);
                    }
                } catch (Exception ex) {
                    ex.printStackTrace();
                }

                logger.debug(">>> 燕禹报文下发开始...........");
                logger.debug(">>> 测站所用通讯号码：telphone = " + telphone);
                logger.debug(">>> 测站配置测站编码：stcd = " + stcd);
                logger.debug(">>> 测站配置测站编码：center = " + center);
                logger.debug(">>> 测站配置测站编码：BORROW = " + borrow);

                //查找报文
                if (StringUtils.isNotBlank(stcd) || StringUtils.isNotBlank(telphone)) {
                    // 读取下发命令，此片仅每次下发一条报文，等待RTU回复报文后，再次发送下一条报文，以达到顺时下发报文的目的。
                    if (StringUtils.isNotBlank(telphone)) {
                        Map<String, Object> stationMap = getStation(telphone);
                        if (stationMap != null) {
                            session.setAttribute("STCD", stationMap.get("STCD"));
                            session.setAttribute("HD", stationMap.get("HD"));
                            session.setAttribute("PROTOCOL", stationMap.get("PROTOCOL"));
                            session.setAttribute("CENTER", stationMap.get("CENTER"));
                            session.setAttribute("BORROW", stationMap.get("BORROW"));
                            stcd = (String) session.getAttribute("STCD");
                            protocol = (String) session.getAttribute("PROTOCOL");
                            hdFlag = (String) session.getAttribute("HD");//是否有宏电模块
                            center = (String) session.getAttribute("CENTER");//中心站地址
                            borrow = (String) session.getAttribute("BORROW");//借位地址
                        }
                    }
                    if (StringUtils.isNotBlank(stcd) && StringUtils.isNotBlank(protocol)) {
//                        File[] downFile = getDownMessage(protocol, stcd);
//                        if (downFile.length > 0) {
//                            File df = downFile[0];
//                            List<String> lines = FileUtils.readLines(df, "UTF-8");
//                            //直接下发报文
//                            WriteFuture f = null;
//                            for (String line : lines) {
                        //修改燕禹召测为redis取下发
                        String YYcallMsg = redisManager.read(stcd + "YYCallder");
                        if (YYcallMsg.length() > 0) {
                            String[] YYcallMsgList = YYcallMsg.split("#");
                            String retuCd = YYcallMsgList[0];//设备号
                            String id = YYcallMsgList[1];//数据库ID
                            String fun = YYcallMsgList[2];//功能码
                            String msg = YYcallMsgList[3];//下发报文

                            logger.debug(">>进入燕禹召测召测信息为：  " + YYcallMsg);
                            //截取功能码
                            String funcode = msg.substring(0, 1);
                            // 发送成功后，需要写入成功标识
                            if (funcode.equals("1")) {
                                //雨量固态数据提取
                                String[] tm = msg.substring(2).split("-");
                                String commd1 = "7e" + borrow + center + "0a09" + tm[0] + tm[1] + "05";
                                msg = commd1 + ByteUtil.byteToHexString(CRC16Helper.crc16Check(ByteUtil.HexStringToBinary(commd1)));
                                //Thread.sleep(60000);
                            } else if (funcode.equals("4")) {
                                //水位固态数据提取
                                String[] tm1 = msg.substring(2).split("-");
                                //下发召测指令
                                String commd2 = "7e" + borrow + center + "0609" + tm1[0] + tm1[1] + "05";
                                //获取CRC校验码
                                msg = commd2 + ByteUtil.byteToHexString(CRC16Helper.crc16Check(ByteUtil.HexStringToBinary(commd2)));
                            } else if (funcode.equals("2")) {
                                //实时数据提取
                                SimpleDateFormat sdf = new SimpleDateFormat("yyMMddHHmmss");
                                String tm = sdf.format(new Date());
                                String commd = "7e" + borrow + center + "0709" + tm + "05";
                                msg = commd + ByteUtil.byteToHexString(CRC16Helper.crc16Check(ByteUtil.HexStringToBinary(commd)));
                            } else if (funcode.equals("3")) {
                                //校时
                                SimpleDateFormat sdf = new SimpleDateFormat("yyMMddHHmmss");
                                String tm = sdf.format(new Date());
                                msg = "";
                            }
                            byte[] rpy_content = ByteUtil.HexStringToBinary(msg);
                            byte[] replyMsg;

                            byte[] dtuCode = telphone.getBytes();
                            replyMsg = HdDownCommand.cmd89DTU("udp", dtuCode, rpy_content);

                            if (!session.isClosing()) {
                                //logger.info("C> " + hexMessage);
                                logger.debug(">> 开始下发【燕禹召测消息】到 " + stcd + " 到客户端，远程地址为：" + session.getRemoteAddress() + "！");
                                WriteFuture f = session.write(replyMsg);
                                // 发送成功后，需要写入成功标识
                                f.addListener(new SessionIoFutureListener(protocol, id, stcd));
                            }
//                                redisManager.writer("YYreplay", id);
//                            }

                        }
                    }
                }

                logger.debug(">>> 宏电报文下发检测完成");
            }
            //---------------------------------------------------------------------------------
            if (StringUtils.isBlank(stcd)) {


               /* if (delay > (Double.parseDouble(onlineNoData) * 60 * 1000)) {//
                    // 此处的时间，可以根据服务器的设置进行调整。（可以改成配置参数来控制）
                    logger.debug(">> 服务端主动清除 无测站编码的站session " + ",测站在线时长为 " + delay / 60000 + " 分钟。");
                    // 将在线的Session从对应的stcd队列中删除
                    removeSession(session);
                    //logger.info( ">> 服务端主动清除无效编码的站session " + ",测站在线时长为 " + delay / 60000 + " 分钟。" );
                    // 关闭session，不进行主动关闭session操作，厂商会发送心跳包过来（可以改成配置参数来控制）
                    //session.close(true);// 不要关闭会话
                }*/

                return;
            }

            //注意需要考虑长连接的情况，如果是长连接，不需要关闭连接,针对湖北、江西的宏电模块，不进行关闭操作
            //if (StringUtils.isBlank(caller) && StringUtils.isBlank(upFlag)) {
            //session.close(true);// 因为session无测站，保持此会话已无意义，
            //   return;
            //} else {
            // 如果有升级程序
            //logger.debug( ">>idleSession caller " + stcd + " upFlag = " + upFlag + " caller = " + caller );
            if (StringUtils.equals(upFlag, "1")) {
                logger.debug("C> 进入统一召测功能");
                String strSeq = (String) session.getAttribute("MSGSEQ");
                if (StringUtils.isNotBlank(strSeq)) {
                    int upSeq = Integer.parseInt(strSeq);
                    // 查找报文，根据upSeq查找下发第几包的报文
                    // 下发所有的报文
                    File file = getBinMessage(stcd);
                    // 读取文件内容，然后下发
                    List<String> lines = FileUtils.readLines(file, "UTF-8");

                    logger.debug(">>发送升级包，第 " + upSeq + " 包. ");

                    if (upSeq == 0) {

                        String line = lines.get(upSeq);
                        byte[] byteMessage = ByteUtil.HexStringToBinary(line);
                        if (!session.isClosing()) {
                            session.write(byteMessage);
                        }
                        session.setAttribute("MSGSEQ", upSeq + 1);

                    } else {
                        // 跳过多少行
                        String line = lines.get(upSeq);
                        byte[] byteMessage = ByteUtil.HexStringToBinary(line);
                        if (!session.isClosing()) {
                            session.write(byteMessage);
                        }
                        session.setAttribute("MSGSEQ", upSeq + 1);
                    }

                    if (upSeq > lines.size()) {
                        // 发送完，需将标志位置为0
                        logger.debug(">>发送到紧后一包后，关闭发送升级包。  size " + lines.size() + " ");
                        RtuServer.getInstance().getSessionManager().bindUpgrade(session, stcd, "0", 0);
                    }
                }
            }
            // -------------------------------------------------------------------------------------------------
            // 如果没有召测信息，则可以进行关闭链接操作，这个操作需要根据项目的情况进行设置，两种设置，一是是主动关闭连接，二是多长时间关闭
            if (StringUtils.equals(protocol, "SL651")) {
                //logger.debug(">> 调用通用协议下发指令 ------------------------------------------------协议：" + protocol);
                // 读取下发命令，此片仅每次下发一条报文，等待RTU回复报文后，再次发送下一条报文，以达到顺时下发报文的目的。

                /*
                File[] downFile = getDownMessage(protocol, stcd);

                if (downFile.length > 0) {
                    File df = downFile[0];
                    List<String> lines = FileUtils.readLines(df, "UTF-8");

                    String id = df.getName();
                    if (lines.size() == 2) {
                        // 获取第一行数据：
                        String line0 = lines.get(0);
                        String[] larr = line0.split(",");
                        String funccode = larr[1];

                        // 获取第二行数据
                        String hexMessage = lines.get(1);
                        if (StringUtils.isNotBlank(hexMessage)) {

                            // 需要根据第一行的数据来判断是下发哪种报文，针对不同协议的校时报，需更新
                            if (StringUtils.equalsIgnoreCase(funccode, "4A")) {
                                // 替换时间部分，并重新生成校验码，然后下发
                                hexMessage = hexMessage.substring(0, 32) + sdf.format(new Date()) + "05";
                                byte[] crcResult = CRC16Helper.crc16Check(ByteUtil.HexStringToBinary(hexMessage));
                                hexMessage = hexMessage + ByteUtil.byteToHexString(crcResult);
                            }
                            byte[] byteMessage = ByteUtil.HexStringToBinary(hexMessage);
                            // 得有一个标志，标志当前的会话已经超时，RTU对方可能没有在上电状态。
                            if (!session.isClosing()) {
                                //logger.info("C> " + hexMessage);
                                logger.debug(">> 开始下发【召测消息】到 " + stcd + " 到客户端，远程地址为：" + session.getRemoteAddress() + "！");
                                WriteFuture f = session.write(byteMessage);
                                // 发送成功后，需要写入成功标识
                                f.addListener(new SessionIoFutureListener(protocol, id, stcd));
                            }
                        }
                    }
                } else {
                    session.setAttribute("CALLER", "0");
                }
*/
                String callMsg = redisManager.read(stcd + "Callder");
                if (callMsg.length() > 0) {
                    //判断是否有多个连接 如果有，是不是最后一个 如果是则下发 否则 重新塞入redis
                    String[] callMsgList = callMsg.split("#");
                    String retuCd = callMsgList[0];//设备号
                    String id = callMsgList[1];//数据库ID
                    String fun = callMsgList[2];//功能码
                    String msg = callMsgList[3];//下发报文
                    if (StringUtils.equalsIgnoreCase(fun, "4A")) {
                        // 替换时间部分，并重新生成校验码，然后下发
                        msg = msg.substring(0, 32) + sdf.format(new Date()) + "05";
                        byte[] crcResult = CRC16Helper.crc16Check(ByteUtil.HexStringToBinary(msg));
                        msg = msg + ByteUtil.byteToHexString(crcResult);
                    }
                    byte[] byteMessage = ByteUtil.HexStringToBinary(msg);
                    //有重复情况 获取所有相同设备号session  下发报文

                    for (IoSession item : inSessions) {
                        if (item.getAttribute("STCD") != null) {
                            String stcdSession = item.getAttribute("STCD").toString();
                            if (stcd.equals(stcdSession)) {
                                try {
                                    if (!item.isClosing()) {
                                        item.write(byteMessage);
                                        logger.info(">> 开始下发【召测消息】到 " + stcd + " 到客户端，远程地址为：" + item.getRemoteAddress() + "！");
                                    }
                                } catch (Exception ex) {
                                    logger.info("下发失败-------------");
                                    ex.printStackTrace();
                                }
                            }
                        }
                    }
                    redisManager.writer("replay", id);
                     /*   // 得有一个标志，标志当前的会话已经超时，RTU对方可能没有在上电状态。
                        if (!session.isClosing()) {
                            //logger.info("C> " + hexMessage);
                            WriteFuture f = session.write(byteMessage);

                            logger.info(">> 开始下发【召测消息】到 " + stcd + " 到客户端，远程地址为：" + session.getRemoteAddress() + "！");
                            // 发送成功后，需要写入成功标识
                            f.addListener(new SessionIoFutureListener(protocol, id, stcd));
                           redisManager.writer("replay", id);

                        } else {
                            redisManager.writer(stcd + "Callder", callMsg);
                        }*/


                }
            }

            //}
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * @param stcd 设备号
     * @param tm   设备的创建时间
     * @return
     */
    public boolean isLastSession(String stcd, long tm) {
        boolean last = false;
        Integer stcdCount = 0;
        HashSet<IoSession> repeatList = new HashSet<IoSession>();
        for (IoSession item : inSessions
        ) {
            if (item.getAttribute("STCD") != null) {
                String stcdSession = item.getAttribute("STCD").toString();
                if (stcd.equals(stcdSession)) {
                    repeatList.add(item);
                    stcdCount++;
                }
            }
        }
        if (stcdCount == 1) {
            last = true;
            logger.info(stcd + "只有一个相同的----------------------------------------------------------");
        } else {
            //判断是否最后一个时间的
            last = true;
            for (IoSession repeatItem : repeatList) {
                logger.info(">> 相同的测站 " + stcd + " 到客户端，远程地址为：" + repeatItem.getRemoteAddress() + "！");
                if (repeatItem.getCreationTime() > tm) {
                    last = false;
                }
            }
        }
        return last;
    }

    public void bindCaller(IoSession session, String stcd, String flag) {
        session.setAttribute("STCD", stcd);
        session.setAttribute("CALLER", flag);
    }


    public void bindUpgrade(IoSession session, String stcd, String flag, int seq) {
        session.setAttribute("STCD", stcd);
        session.setAttribute("UPGRADE", flag);
        session.setAttribute("MSGSEQ", seq);
    }

    public void bindSession(IoSession session, String protocol, String stcd) {
        session.setAttribute("STCD", stcd);
        session.setAttribute("PROTOCOL", protocol);
    }

    public void bindYYSession(IoSession session, String stcd, String center, String borrow) {
        session.setAttribute("STCD", stcd);
        session.setAttribute("PROTOCOL", "YY");
        session.setAttribute("CENTER", center);
        session.setAttribute("BORROW", borrow);
        session.setAttribute("HD", "0");
    }

    /**
     * 宏电带数据的心跳包
     *
     * @param session
     * @param tel
     * @param stcd
     * @param center
     * @param borrow
     */
    public void bindHdSession(IoSession session, String tel, String stcd, String center, String borrow) {
        session.setAttribute("PROTOCOL", "YY");
        session.setAttribute("TELPHONE", tel);
        session.setAttribute("CENTER", center);
        session.setAttribute("STCD", stcd);
        session.setAttribute("BORROW", borrow);
        session.setAttribute("HD", "1");
    }

    /**
     * 宏电心跳包
     *
     * @param session
     * @param tel
     */
    public void bindHdSession(IoSession session, String tel) {
        session.setAttribute("PROTOCOL", "YY");
        session.setAttribute("TELPHONE", tel);
        session.setAttribute("HD", "1");
    }
    /**
     * 下发测站指令,下发的是水文协议消息体
     *
     * @param stcd
     * @param message
     */
    // public void downMessage(String stcd, IMessage message) {
    // ClientInfo client = clients.get(stcd);;
    // if (client!=null) {
    // //client = clients.get(stcd);
    // IoSession session = client.getSession();
    // if (!session.isClosing()) {
    // logger.info(">>下发<<HydroMessage Info>>给客户端："
    // + session.getRemoteAddress());
    // session.write(message);
    // }
    // }
    // }

    /**
     * 广播消息
     *
     * @param message
     */
    public void broadcast(byte[] message) {
        // logger.error("中心站开始发送下发指令！");
        synchronized (inSessions) {
            for (IoSession session : inSessions) {
                if (!session.isClosing()) {
                    logger.debug(">>指令下发给客户端：" + session.getRemoteAddress());
                    session.write(message);
                }
            }
        }

    }

    /**
     * 检测是否有下发命令，如果有，则需要将标识切换为等待状态，如果无，则正常状态
     *
     * @return
     */
    public File[] getDownMessage(String protocol, String stcd) {

        String path = RtuConfig.getMsgCmdPath();
        path = path + "/msg/" + protocol + "/" + stcd + "/";
        File fullPathDir = new File(path);
        if (fullPathDir != null && !fullPathDir.exists()) {
            fullPathDir.mkdirs();
        }

        return fullPathDir.listFiles();

    }

    /**
     * 报文程序的目录
     *
     * @param stcd
     * @return
     */
    public File getBinMessage(String stcd) {

        String path = RtuConfig.getMsgBinPath();

        path = path + "/" + stcd + ".sbin";

        File fullPathDir = new File(path);
        if (fullPathDir != null && !fullPathDir.exists()) {
            fullPathDir.mkdirs();
        }

        File binFile = new File(path);

        if (binFile.exists()) {
            return binFile;
        } else {
            return null;
        }
    }

    /**
     * 根据电话号码获取redis缓存中的测站基本信息 - 针对燕禹
     *
     * @param stcd
     * @return
     */
    public Map<String, Object> getStation(String tel) {
        RedisTemplate redisTemplate;
        Map<String, Object> stationMap = new HashMap<String, Object>();
        redisTemplate = (RedisTemplate) Application.getInstance().getCtx().getBean("redisTemplate");
        if (redisTemplate == null) {
            logger.info(">> 无监控终端！");
        } else {
            ValueOperations station = redisTemplate.opsForValue();
            List<Map<String, Object>> stationList = (List<Map<String, Object>>) station.get("station");
            if (stationList != null) {
                for (int i = 0; i < stationList.size(); i++) {
                    if (stationList.get(i).get("TELPHONE") != null) {
                        String telphone = stationList.get(i).get("TELPHONE").toString();
                        if (tel.equals(telphone)) {
                            stationMap = stationList.get(i);
                            return stationMap;
                        }
                    }
                }
            }
        }
        return stationMap;
    }

    public static void main(String[] args) {
        String crcStr = ByteUtil.byteToHexString(CRC16Helper.crc16Check(ByteUtil.HexStringToBinary("7e0ffe0a0917071817080105"))); //获取CRC
        String crcStr1 = ByteUtil.byteToHexString(CRC16Helper.crc16Check(ByteUtil.HexStringToBinary("7e0ffe060917071817080105")));
        String hexMessage = "7E7E00123456780199994A8008020001161125104822051961";
        hexMessage = hexMessage.substring(0, 32) + sdf.format(new Date())
                + "05";
        logger.info(">> hexMessage " + hexMessage);
        byte[] crcResult = CRC16Helper.crc16Check(ByteUtil
                .HexStringToBinary(hexMessage));

        hexMessage = hexMessage + ByteUtil.byteToHexString(crcResult);
        logger.info(">> hexMessage " + hexMessage);

        File fullPathDir = new File("D:/rcvApp/bin/1111");
        if (fullPathDir != null && !fullPathDir.exists()) {
            fullPathDir.mkdirs();
        }

        // 按文件名排序
        List<File> files = Arrays.asList(fullPathDir.listFiles());
        // Collections.sort(files, new Comparator<File>(){
        // @Override
        // public int compare(File o1, File o2) {
        // if(o1.isDirectory() && o2.isFile())
        // return -1;
        // if(o1.isFile() && o2.isDirectory())
        // return 1;
        // return o1.getName().compareTo(o2.getName());
        // }
        // });

        for (File f : files)
            logger.info(f.getName());
    }

}
